﻿using RotovapPlatform.Domain.Business.Interfaces;
using RotovapPlatform.Domain.Business.Storage.Entities;
using RotovapPlatform.Domain.Business.Storage.Entities.Base;
using RotovapPlatform.Domain.Business.Storage.Entities.Bottles;
using RotovapPlatform.Domain.Business.Storage.Enums;
using static RotovapPlatform.Domain.Business.Machine.Enums.ExperimentConfigEnums;

namespace RotovapPlatform.Domain.Services.Storages
{
	/// <summary>
	/// 存储服务实现
	/// 实现物料管理的业务逻辑
	/// </summary>
	public class StorageDomainService : IStorageDomainService
	{
		private readonly IStorageLocationRepository _repository;

		public StorageDomainService(IStorageLocationRepository repository)
		{
			_repository = repository;
		}

		/// <summary>
		/// 获取所有货架位置
		/// </summary>
		public async Task<List<StorageLocation>> GetAllShelfLocationsAsync()
		{
			var locations = await _repository.GetByLocationCodeAsync(LocationCode.Shelf);
			return locations.ToList();
		}

		/// <summary>
		/// 获取指定货架位置
		/// </summary>
		public async Task<StorageLocation?> GetShelfLocationAsync(LocationCode locationCode, int position)
		{
			// 强制从数据库获取最新数据，不使用缓存
			return await _repository.GetByPositionAsync(locationCode, position, true);
		}

		/// <summary>
		/// 根据ID获取货架位置
		/// </summary>
		public async Task<StorageLocation?> GetShelfLocationByIdAsync(int id)
		{
			// 实现直接从数据库获取最新数据的逻辑
			// 1. 先清除上下文中的跟踪实体
			// 2. 再直接从数据库获取
			var location = await _repository.GetByIdAsync(id);

			// 如果找到了对应ID的位置，并且需要最新数据
			if (location != null)
			{
				// 使用位置代码和位置号强制从数据库获取最新数据
				return await _repository.GetByPositionAsync(location.LocationCode, location.Position, true);
			}

			return null;
		}

		/// <summary>
		/// 获取所有工作站位置
		/// </summary>
		public async Task<List<StorageLocation>> GetStationLocationsAsync(LocationCode stationType)
		{
			if (stationType != LocationCode.TransferStation &&
				stationType != LocationCode.LiquidHandlingStation)
			{
				throw new ArgumentException("Invalid station type", nameof(stationType));
			}

			var locations = await _repository.GetByLocationCodeAsync(stationType);
			return locations.ToList();
		}

		/// <summary>
		/// 获取可以放置指定物品类型的空闲货架位置
		/// </summary>
		public async Task<List<StorageLocation>> GetAvailableShelfLocationsForItemTypeAsync(ItemType itemType)
		{
			// 强制从数据库获取最新数据，使用AsNoTracking避免缓存问题
			var allLocations = await _repository.GetByLocationCodeAsync(LocationCode.Shelf, true);

			// 返回未占用且支持指定物品类型的位置，同时要求IsReserved为0（未预占位）
			var emptyLocations = allLocations
				.Where(l => !l.IsOccupied && l.IsReserved == 0 && l.SupportedItemTypes.Contains(itemType))
				.ToList();

			// 合并两种位置列表并返回
			return emptyLocations;
		}

		/// <summary>
		/// 获取已占用但有可用瓶子的货架位置
		/// </summary>
		/// <param name="bottleType">瓶子类型</param>
		/// <returns>有可用瓶子的位置列表</returns>
		public async Task<List<StorageLocation>> GetAvailableBottleLocationsAsync(ItemType bottleType)
		{
			// 强制从数据库获取最新数据，使用AsNoTracking避免缓存问题
			var allLocations = await _repository.GetByLocationCodeAsync(LocationCode.Shelf, true);
			var occupiedLocations = new List<StorageLocation>();

			if (bottleType == ItemType.Rotovap_500ml || bottleType == ItemType.Rotovap_1000ml)
			{
				// 查找对应类型的干净空旋蒸瓶
				occupiedLocations = allLocations
					.Where(l => l.IsOccupied && l.IsReserved == 0 &&
						l.CurrentItem is RotovapBottle bottle &&
						bottle.Type == bottleType &&
						bottle.IsClean &&
						bottle.Function == FunctionType.Rotovap_Empty)
					.ToList();
			}
			else if (bottleType == ItemType.CentrifugeBottle_500ml)
			{
				// 查找空离心瓶
				occupiedLocations = allLocations
					.Where(l => l.IsOccupied && l.IsReserved == 0 &&
						l.CurrentItem is CentrifugeBottle bottle &&
						bottle.Function == FunctionType.Centrifuge_Empty &&
						!bottle.ExperimentId.HasValue)
					.ToList();
			}
			else if (bottleType == ItemType.SampleBottle_8ml)
			{
				// 查找空取样瓶
				occupiedLocations = allLocations
					.Where(l => l.IsOccupied && l.IsReserved == 0 &&
						l.CurrentItem is SampleBottle bottle &&
						bottle.Function == FunctionType.Sample_Empty &&
						!bottle.ExperimentId.HasValue)
					.ToList();
			}

			return occupiedLocations;
		}

		/// <summary>
		/// 获取指定瓶子类型和指定IsReserved状态的货架位置
		/// </summary>
		/// <param name="bottleType">瓶子类型</param>
		/// <param name="reservedStatus">预占位状态（0:未预占位,1:预占位但未使用,2:预占位且已使用）</param>
		/// <returns>符合条件的货架位置列表</returns>
		public async Task<List<StorageLocation>> GetBottleLocationsByReservedStatusAsync(ItemType bottleType, int reservedStatus)
		{
			// 验证预占位状态值是否有效
			if (reservedStatus < 0 || reservedStatus > 2)
			{
				throw new ArgumentOutOfRangeException(nameof(reservedStatus), "预占位状态值必须在0-2范围内");
			}

			// 验证瓶子类型是否有效
			bool isValidBottleType = bottleType == ItemType.Rotovap_500ml ||
				bottleType == ItemType.Rotovap_1000ml ||
				bottleType == ItemType.CentrifugeBottle_500ml ||
				bottleType == ItemType.SampleBottle_8ml;

			if (!isValidBottleType)
			{
				throw new ArgumentException($"无效的瓶子类型: {bottleType}", nameof(bottleType));
			}

			// 强制从数据库获取最新数据，使用AsNoTracking避免缓存问题
			var allLocations = await _repository.GetByLocationCodeAsync(LocationCode.Shelf, true);
			var matchingLocations = new List<StorageLocation>();

			if (bottleType == ItemType.Rotovap_500ml || bottleType == ItemType.Rotovap_1000ml)
			{
				// 查找符合条件的旋蒸瓶位置
				matchingLocations = allLocations
					.Where(l => l.IsOccupied && l.IsReserved == reservedStatus &&
						l.CurrentItem is RotovapBottle bottle &&
						bottle.Type == bottleType)
					.ToList();
			}
			else if (bottleType == ItemType.CentrifugeBottle_500ml)
			{
				// 查找符合条件的离心瓶位置
				matchingLocations = allLocations
					.Where(l => l.IsOccupied && l.IsReserved == reservedStatus &&
						l.CurrentItem is CentrifugeBottle bottle)
					.ToList();
			}
			else if (bottleType == ItemType.SampleBottle_8ml)
			{
				// 查找符合条件的取样瓶位置
				matchingLocations = allLocations
					.Where(l => l.IsOccupied && l.IsReserved == reservedStatus &&
						l.CurrentItem is SampleBottle bottle)
					.ToList();
			}

			return matchingLocations;
		}

		/// <summary>
		/// 将物品放入指定货架位置
		/// </summary>
		public async Task<StorageLocation> PlaceItemAsync(int locationId, IStorageItem item)
		{
			var location = await _repository.GetByIdAsync(locationId);
			if (location == null)
			{
				throw new ArgumentException($"Location with ID {locationId} not found", nameof(locationId));
			}

			if (location.IsOccupied)
			{
				throw new InvalidOperationException($"Location {locationId} is already occupied");
			}

			if (!location.SupportedItemTypes.Contains(item.Type))
			{
				throw new InvalidOperationException($"Location {locationId} does not support item type {item.Type}");
			}

			location.SetItem(item);
			await _repository.UpdateAsync(location);
			return location;
		}

		/// <summary>
		/// 从指定货架位置取出物品
		/// </summary>
		public async Task<IStorageItem?> RemoveItemAsync(int locationId)
		{
			var location = await _repository.GetByIdAsync(locationId);
			if (location == null)
			{
				throw new ArgumentException($"Location with ID {locationId} not found", nameof(locationId));
			}

			if (!location.IsOccupied)
			{
				return null;
			}

			var item = location.RemoveItem();
			await _repository.UpdateAsync(location);
			return item;
		}

		/// <summary>
		/// 检查物品是否可以放入指定位置
		/// </summary>
		public async Task<bool> CanPlaceItemTypeAsync(int locationId, ItemType itemType)
		{
			var location = await _repository.GetByIdAsync(locationId);
			if (location == null)
			{
				return false;
			}

			return !location.IsOccupied && location.SupportedItemTypes.Contains(itemType);
		}

		/// <summary>
		/// 获取货架位置的显示名称
		/// 例如：位置101对应货架1-1
		/// </summary>
		public string GetShelfDisplayName(int position)
		{
			// 假设位置编号格式为：百位数表示行，个位数表示列
			// 例如：101表示第1行第1列，即货架1-1
			int row = position / 100;
			int column = position % 100;
			return $"货架{row}-{column}";
		}

		/// <summary>
		/// 根据显示名称获取货架位置编号
		/// 例如：货架1-1对应位置101
		/// </summary>
		public int GetShelfPositionFromDisplayName(string displayName)
		{
			// 解析格式为"货架{row}-{column}"的显示名称
			if (!displayName.StartsWith("货架"))
			{
				throw new ArgumentException("Invalid display name format", nameof(displayName));
			}

			var parts = displayName.Substring(2).Split('-');
			if (parts.Length != 2 || !int.TryParse(parts[0], out int row) || !int.TryParse(parts[1], out int column))
			{
				throw new ArgumentException("Invalid display name format", nameof(displayName));
			}

			return row * 100 + column;
		}

		/// <summary>
		/// 将物品放入指定货架位置（通过位置编号）
		/// </summary>
		public async Task<StorageLocation> PlaceItemByPositionAsync(LocationCode locationCode, int position, IStorageItem item)
		{
			// 先获取位置信息
			var location = await GetShelfLocationAsync(locationCode, position);
			if (location == null)
			{
				throw new InvalidOperationException($"未找到位置: {locationCode}-{position}");
			}

			// 检查物品类型是否支持
			if (!location.SupportedItemTypes.Contains(item.Type))
			{
				throw new InvalidOperationException($"位置 {position} 不支持 {item.Type} 类型的物品");
			}

			// 检查位置是否已被占用
			if (location.IsOccupied)
			{
				throw new InvalidOperationException($"位置 {position} 已被占用");
			}

			// 设置物品
			location.SetItem(item);

			// 更新数据库
			await _repository.UpdateAsync(location);

			return location;
		}

		/// <summary>
		/// 从指定货架位置取出物品（通过位置编号）
		/// </summary>
		public async Task<IStorageItem?> RemoveItemByPositionAsync(LocationCode locationCode, int position)
		{
			// 先获取位置信息
			var location = await GetShelfLocationAsync(locationCode, position);
			if (location == null)
			{
				throw new InvalidOperationException($"未找到位置: {locationCode}-{position}");
			}

			// 检查位置是否有物品
			if (!location.IsOccupied || location.CurrentItem == null)
			{
				throw new InvalidOperationException($"位置 {position} 没有物品");
			}

			// 取出物品
			var item = location.RemoveItem();

			// 更新数据库
			await _repository.UpdateAsync(location);

			return item;
		}

		/// <summary>
		/// 检查物品是否可以放入指定位置（通过位置编号）
		/// </summary>
		public async Task<bool> CanPlaceItemTypeByPositionAsync(LocationCode locationCode, int position, ItemType itemType)
		{
			// 先获取位置信息
			var location = await GetShelfLocationAsync(locationCode, position);
			if (location == null)
			{
				return false;
			}

			// 检查位置是否已被占用和物品类型是否支持
			return !location.IsOccupied && location.SupportedItemTypes.Contains(itemType);
		}

		/// <summary>
		/// 验证指定名称的物料是否存在于货架上
		/// </summary>
		public async Task<bool> MaterialExistsAsync(string materialName, FunctionType functionType)
		{
			if (string.IsNullOrWhiteSpace(materialName))
			{
				return false;
			}

			// 获取所有货架位置
			var allLocations = await GetAllShelfLocationsAsync();

			// 验证物料是否存在于货架上
			return allLocations.Any(loc =>
				loc.CurrentItem != null &&
				loc.CurrentItem is CentrifugeBottle bottle &&
				bottle.MaterialName == materialName &&
				bottle.Function == functionType);
		}

		/// <summary>
		/// 验证物料和清洗液是否存在于货架上
		/// </summary>
		public async Task<(bool IsValid, string ErrorMessage)> ValidateMaterialsExistenceAsync(
			string materialName,
			string condensationCleaningSolution,
			string rotaryBottleCleaningSolution)
		{
			// 验证物料名称
			if (string.IsNullOrWhiteSpace(materialName))
			{
				return (false, "待旋蒸物料名称不能为空");
			}

			// 获取所有货架位置
			var allLocations = await GetAllShelfLocationsAsync();

			// 验证物料是否存在于货架上
			var materialExists = allLocations.Any(loc =>
				loc.CurrentItem != null &&
				loc.CurrentItem is CentrifugeBottle bottle &&
				bottle.MaterialName == materialName &&
				bottle.Function == FunctionType.Centrifuge_To_Rotovap);

			if (!materialExists)
			{
				return (false, $"货架上不存在名为 '{materialName}' 的待旋蒸物料");
			}

			// 验证冷凝器清洗液是否存在
			if (!string.IsNullOrWhiteSpace(condensationCleaningSolution))
			{
				var condensationCleaningSolutionExists = allLocations.Any(loc =>
					loc.CurrentItem != null &&
					loc.CurrentItem is CentrifugeBottle bottle &&
					bottle.MaterialName == condensationCleaningSolution &&
					bottle.Function == FunctionType.Centrifuge_Wash_Liquid);

				if (!condensationCleaningSolutionExists)
				{
					return (false, $"货架上不存在名为 '{condensationCleaningSolution}' 的清洗液");
				}
			}

			// 验证旋蒸瓶清洗液是否存在
			if (!string.IsNullOrWhiteSpace(rotaryBottleCleaningSolution))
			{
				var rotaryBottleCleaningSolutionExists = allLocations.Any(loc =>
					loc.CurrentItem != null &&
					loc.CurrentItem is CentrifugeBottle bottle &&
					bottle.MaterialName == rotaryBottleCleaningSolution &&
					bottle.Function == FunctionType.Centrifuge_Wash_Liquid);

				if (!rotaryBottleCleaningSolutionExists)
				{
					return (false, $"货架上不存在名为 '{rotaryBottleCleaningSolution}' 的清洗液");
				}
			}

			return (true, string.Empty);
		}

		/// <summary>
		/// 验证货架上是否有足够的瓶子用于实验
		/// </summary>
		/// <param name="requiredRotovapBottles500ml">所需500ml旋蒸瓶数量</param>
		/// <param name="requiredRotovapBottles1000ml">所需1000ml旋蒸瓶数量</param>
		/// <param name="requiredCentrifugeBottles">所需离心瓶数量</param>
		/// <param name="requiredSampleBottles">所需采样瓶数量</param>
		/// <returns>验证结果和错误信息</returns>
		public async Task<(bool IsValid, string ErrorMessage)> ValidateBottleAvailabilityAsync(
			int requiredRotovapBottles500ml,
			int requiredRotovapBottles1000ml,
			int requiredCentrifugeBottles,
			int requiredSampleBottles)
		{
			try
			{
				// 获取所有货架位置
				var allLocations = await GetAllShelfLocationsAsync();

				// 统计可用的瓶子数量
				int availableRotovapBottles500ml = allLocations.Count(loc =>
					loc.CurrentItem != null &&
					loc.CurrentItem is RotovapBottle bottle &&
					bottle.IsClean &&
					bottle.Function == FunctionType.Rotovap_Empty &&
					bottle.Type == ItemType.Rotovap_500ml);

				int availableRotovapBottles1000ml = allLocations.Count(loc =>
					loc.CurrentItem != null &&
					loc.CurrentItem is RotovapBottle bottle &&
					bottle.IsClean &&
					bottle.Function == FunctionType.Rotovap_Empty &&
					bottle.Type == ItemType.Rotovap_1000ml);

				int availableCentrifugeBottles = allLocations.Count(loc =>
					loc.CurrentItem != null &&
					loc.CurrentItem is CentrifugeBottle bottle &&
					bottle.Function == FunctionType.Centrifuge_Empty &&
					!bottle.ExperimentId.HasValue);

				int availableSampleBottles = allLocations.Count(loc =>
					loc.CurrentItem != null &&
					loc.CurrentItem is SampleBottle bottle &&
					bottle.Function == FunctionType.Sample_Empty &&
					!bottle.ExperimentId.HasValue);

				// 检查是否有足够的瓶子
				var errorMessages = new List<string>();

				if (availableRotovapBottles500ml < requiredRotovapBottles500ml)
				{
					errorMessages.Add($"货架上可用的500ml旋蒸瓶不足，需要 {requiredRotovapBottles500ml} 个，但只有 {availableRotovapBottles500ml} 个");
				}

				if (availableRotovapBottles1000ml < requiredRotovapBottles1000ml)
				{
					errorMessages.Add($"货架上可用的1000ml旋蒸瓶不足，需要 {requiredRotovapBottles1000ml} 个，但只有 {availableRotovapBottles1000ml} 个");
				}

				if (availableCentrifugeBottles < requiredCentrifugeBottles)
				{
					errorMessages.Add($"货架上可用的离心瓶不足，需要 {requiredCentrifugeBottles} 个，但只有 {availableCentrifugeBottles} 个");
				}

				if (availableSampleBottles < requiredSampleBottles)
				{
					errorMessages.Add($"货架上可用的采样瓶不足，需要 {requiredSampleBottles} 个，但只有 {availableSampleBottles} 个");
				}

				if (errorMessages.Any())
				{
					return (false, string.Join(Environment.NewLine, errorMessages));
				}

				return (true, string.Empty);
			}
			catch (Exception ex)
			{
				return (false, $"验证瓶子可用性时发生错误: {ex.Message}");
			}
		}

		/// <summary>
		/// 更新货架位置信息
		/// </summary>
		/// <param name="location">需要更新的货架位置</param>
		/// <returns>更新任务</returns>
		public async Task UpdateShelfLocationAsync(StorageLocation location)
		{
			if (location == null)
				throw new ArgumentNullException(nameof(location), "货架位置不能为null");

			// 在更新前对属性变更进行日志记录
			Console.WriteLine($"正在更新货架位置: ID={location.Id}, 位置={location.LocationCode}-{location.Position}, IsReserved={location.IsReserved}");

			// 更新数据库记录
			await _repository.UpdateAsync(location);

			// 检查更新是否成功
			var freshLocation = await _repository.GetByPositionAsync(location.LocationCode, location.Position, true);
			if (freshLocation != null)
			{
				Console.WriteLine($"更新后的货架位置: ID={freshLocation.Id}, 位置={freshLocation.LocationCode}-{freshLocation.Position}, IsReserved={freshLocation.IsReserved}");
			}
			else
			{
				Console.WriteLine($"警告：无法验证更新后的货架位置状态，位置：{location.LocationCode}-{location.Position}");
			}
		}
	}
}